<script lang="ts" setup>

import type { Recordable } from '@vben/types';

import type { VbenFormSchema } from '#/adapter/form';

import { computed, h, ref } from 'vue';

import { useVbenDrawer } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import { $te } from '@vben/locales';
import { getPopupContainer } from '@vben/utils';

import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';

import { useVbenForm, z } from '#/adapter/form';
import {
  createMenu,
  getMenuTree,
  SystemMenuApi,
  updateMenu,
} from '#/api/system/menu';
import { $t } from '#/locales';
import { componentKeys } from '#/router/routes';

import { getMenuTypeOptions } from '../data';

const emit = defineEmits<{
  success: [];
  closeDrawer: [];
}>();
const formData = ref<SystemMenuApi.SystemMenu>();
const loading = ref(false);
const titleSuffix = ref<string>();
const schema: VbenFormSchema[] = [
  {
    component: 'RadioGroup',
    componentProps: {
      size: 'default',
      options: getMenuTypeOptions(),
      isButton: true,
    },
    defaultValue: 'menu',
    fieldName: 'type',
    formItemClass: 'col-span-2 md:col-span-2',
    label: $t('system.menu.type'),
  },
  {
    component: 'Input',
    fieldName: 'name',
    label: $t('system.menu.menuName'),
    rules: z
      .string()
      .min(2, $t('ui.formRules.minLength', [$t('system.menu.menuName'), 2]))
      .max(30, $t('ui.formRules.maxLength', [$t('system.menu.menuName'), 30]))

  },
  {
    component: 'ApiTreeSelect',
    componentProps: {
      api: getMenuTree,
      class: 'w-full',
      checkStrictly: true, //它允许选择任何节点
      afterFetch: (data: SystemMenuApi.SystemMenu[]) => {
        return data.map(item => {
          // 递归处理每个节点，确保翻译标题正确显示
          const processNode = (node: SystemMenuApi.SystemMenu) => {
            // 添加label属性，存储翻译后的文本
            const newNode = {
              ...node,
              label: node.meta?.title ? $t(node.meta.title) : node.name,
            };

            // 如果有子节点，递归处理
            if (node.children && node.children.length > 0) {
              newNode.children = node.children.map(child => processNode(child));
            }

            return newNode;
          };

          return processNode(item);
        });
      },
      filterTreeNode(input: string, node: Recordable<any>) {
        if (!input || input.length === 0) {
          return true;
        }
        const title: string = node.meta?.title ?? '';
        if (!title) return false;
        return title.includes(input) || $t(title).includes(input);
      },
      getPopupContainer,
      labelField: 'label', // 使用afterFetch中添加的label字段
      showSearch: true,
      treeDefaultExpandAll: true,
      valueField: 'id',
      childrenField: 'children',
    },
    fieldName: 'parentId', // 修改为parentId与后端模型保持一致
    label: $t('system.menu.parent'),
    renderComponentContent() {
      return {
        title({ label, meta }: { label: string; meta: Recordable<any> }) {
          const coms = [];
          if (!label) return '';
          if (meta?.icon) {
            coms.push(h(IconifyIcon, { class: 'size-4', icon: meta.icon }));
          }
          coms.push(h('span', { class: '' }, label)); // 直接使用label，因为已经在afterFetch中翻译
          return h('div', { class: 'flex items-center gap-1' }, coms);
        },
      };
    },
  },
  {
    component: 'Input',
    componentProps() {
      return {
        append: titleSuffix.value,
        onChange: (value: string) => {
          titleSuffix.value = value && $te(value) ? $t(value) : undefined;
        },
      };
    },
    fieldName: 'meta.title',
    label: $t('system.menu.menuTitle'),
    rules: 'required',
  },
  {
    component: 'Input',
    dependencies: {
      show: (values) => {
        return ['catalog', 'embedded', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'path',
    label: $t('system.menu.path'),
    rules: z
      .string()
      .min(2, $t('ui.formRules.minLength', [$t('system.menu.path'), 2]))
      .max(100, $t('ui.formRules.maxLength', [$t('system.menu.path'), 100]))
      .refine(
        (value: string) => {
          return value.startsWith('/');
        },
        $t('ui.formRules.startWith', [$t('system.menu.path'), '/']),
      )
  },
  {
    component: 'Input',
    dependencies: {
      show: (values) => {
        return ['embedded', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'activePath',
    help: $t('system.menu.activePathHelp'),
    label: $t('system.menu.activePath'),
    rules: z
      .string()
      .min(2, $t('ui.formRules.minLength', [$t('system.menu.path'), 2]))
      .max(100, $t('ui.formRules.maxLength', [$t('system.menu.path'), 100]))
      .refine(
        (value: string) => {
          return value.startsWith('/');
        },
        $t('ui.formRules.startWith', [$t('system.menu.path'), '/']),
      )

      .optional(),
  },
  {
    component: 'IconPicker',
    componentProps: {
      prefix: 'carbon',
    },
    dependencies: {
      show: (values) => {
        return ['catalog', 'embedded', 'link', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.icon',
    label: $t('system.menu.icon'),
  },
  {
    component: 'IconPicker',
    componentProps: {
      prefix: 'carbon',
    },
    dependencies: {
      show: (values) => {
        return ['catalog', 'embedded', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.activeIcon',
    label: $t('system.menu.activeIcon'),
  },
  {
    component: 'AutoComplete',
    componentProps: {
      allowClear: true,
      class: 'w-full',
      options: componentKeys.map((v) => ({ value: v })),
    },
    dependencies: {
      rules: (values) => {
        return values.type === 'menu' ? 'required' : null;
      },
      show: (values) => {
        return values.type === 'menu';
      },
      triggerFields: ['type'],
    },
    fieldName: 'component',
    label: $t('system.menu.component'),
  },
  {
    component: 'Input',
    dependencies: {
      show: (values) => {
        return ['embedded', 'link'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'linkSrc',
    label: $t('system.menu.linkSrc'),
    rules: z.string().url($t('ui.formRules.invalidURL')),
  },
  {
    component: 'Input',
    dependencies: {
      rules: (values) => {
        return values.type === 'button' ? 'required' : null;
      },
      show: (values) => {
        return ['button', 'catalog', 'embedded', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'authCode',
    label: $t('system.menu.authCode'),
  },
  {
    component: 'RadioGroup',
    componentProps: {
      size: 'default',
      options: [
        { label: $t('common.enabled'), value: 1 },
        { label: $t('common.disabled'), value: 0 },
      ],
      isButton: true,
    },
    defaultValue: 1,
    fieldName: 'status',
    label: $t('system.menu.status'),
  },
  {
    component: 'Select',
    componentProps: {
      allowClear: true,
      class: 'w-full',
      options: [
        { label: $t('system.menu.badgeType.dot'), value: 'dot' },
        { label: $t('system.menu.badgeType.normal'), value: 'normal' },
      ],
    },
    dependencies: {
      show: (values) => {
        return values.type !== 'button';
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.badgeType',
    label: $t('system.menu.badgeType.title'),
  },
  {
    component: 'Input',
    componentProps: (values) => {
      return {
        allowClear: true,
        class: 'w-full',
        disabled: values.meta?.badgeType !== 'normal',
      };
    },
    dependencies: {
      show: (values) => {
        return values.type !== 'button';
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.badge',
    label: $t('system.menu.badge'),
  },
  {
    component: 'Select',
    componentProps: {
      allowClear: true,
      class: 'w-full',
      options: SystemMenuApi.BadgeVariants.map((v) => ({
        label: v,
        value: v,
      })),
    },
    dependencies: {
      show: (values) => {
        return values.type !== 'button';
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.badgeVariants',
    label: $t('system.menu.badgeVariants'),
  },
  {
    component: 'Divider',
    dependencies: {
      show: (values) => {
        return !['button', 'link'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'divider1',
    formItemClass: 'col-span-2 md:col-span-2 pb-0',
    hideLabel: true,
    renderComponentContent() {
      return {
        default: () => $t('system.menu.advancedSettings'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return ['menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.keepAlive',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.keepAlive'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return ['embedded', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.affixTab',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.affixTab'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return !['button'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.hideInMenu',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.hideInMenu'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return ['catalog', 'menu'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.hideChildrenInMenu',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.hideChildrenInMenu'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return !['button', 'link'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.hideInBreadcrumb',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.hideInBreadcrumb'),
      };
    },
  },
  {
    component: 'Checkbox',
    dependencies: {
      show: (values) => {
        return !['button', 'link'].includes(values.type);
      },
      triggerFields: ['type'],
    },
    fieldName: 'meta.hideInTab',
    renderComponentContent() {
      return {
        default: () => $t('system.menu.hideInTab'),
      };
    },
  },
];

const breakpoints = useBreakpoints(breakpointsTailwind);
// 使用响应式断点工具，基于tailwind的断点定义（如sm、md、lg等）
// 用于在不同屏幕宽度下调整界面布局

const isHorizontal = computed(() => breakpoints.greaterOrEqual('md').value);
// 计算属性：当屏幕宽度大于等于'md'断点时返回true
// 用于决定表单是水平布局还是垂直布局

const [Form, formApi] = useVbenForm({
  // 使用Vben Admin框架的表单组件，解构返回Form组件和formApi操作对象
  commonConfig: {
    colon: true, // 设置表单项标签后显示冒号
    formItemClass: 'col-span-2 md:col-span-1', // 表单项CSS类，在移动端占2列，桌面端占1列
  },
  schema, // 表单结构定义，包含字段配置、验证规则等
  showDefaultActions: false, // 不显示默认的表单操作按钮
  wrapperClass: 'grid-cols-2 gap-x-4', // 表单容器CSS类，使用网格布局，2列，水平间隔4单位
});

const [Drawer, drawerApi] = useVbenDrawer({
  // 使用Vben Admin的抽屉组件，解构返回Drawer组件和drawerApi操作对象
  onBeforeClose() {
    if (loading.value) return false; // 如果正在加载中，阻止抽屉关闭
  },
  onConfirm: onSubmit, // 设置抽屉确认按钮的回调函数为onSubmit
  onOpenChange(isOpen) {
    // 抽屉打开状态改变时的回调
    if (isOpen) {
      // 当抽屉打开时执行
      const data = drawerApi.getData<SystemMenuApi.SystemMenu>();
      // 获取传递给抽屉的数据，指定类型为SystemMenuApi.SystemMenu

      // 特殊处理链接类型的菜单
      if (data?.type === 'link') {
        // 如果是外部链接类型，将meta.link值赋给linkSrc字段
        data.linkSrc = data.meta?.link;
      } else if (data?.type === 'embedded') {
        // 如果是内嵌页面类型，将meta.iframeSrc值赋给linkSrc字段
        data.linkSrc = data.meta?.iframeSrc;
      }

      if (data) {
        // 如果有数据（编辑模式）
        formData.value = data; // 设置表单数据
        // 确保表单填充时使用parentId字段
        if (formData.value.parentId) {
          formApi.setFieldValue('parentId', formData.value.parentId);
        }
        formApi.setValues(formData.value); // 将数据填充到表单中
        titleSuffix.value = formData.value.meta?.title
          ? $t(formData.value.meta.title) // 如果有标题，通过i18n翻译
          : '';
      } else {
        // 如果没有数据（新建模式）
        formApi.resetForm(); // 重置表单
        titleSuffix.value = ''; // 清空标题后缀
      }
    }
  },
});

async function onSubmit() {
  // 表单提交处理函数
  const { valid } = await formApi.validate();
  // 验证表单，获取验证结果

  if (valid) {
    // 如果验证通过
    loading.value = true;
    // 设置加载状态为true

    // 设置抽屉状态，防止用户中途关闭
    drawerApi.setState({
      closeOnClickModal: false, // 禁止点击模态背景关闭
      closeOnPressEscape: false, // 禁止按Esc关闭
      confirmLoading: true, // 确认按钮显示加载状态
      loading: true, // 抽屉显示加载状态
    });

    // 获取表单值，并指定类型（排除children和id字段）
    const data =
      await formApi.getValues<
        Omit<SystemMenuApi.SystemMenu, 'children' | 'id'>
      >();

    // 根据菜单类型特殊处理链接地址
    if (data.type === 'link') {
      // 如果是外部链接类型，将linkSrc值存入meta.link
      data.meta = { ...data.meta, link: data.linkSrc };
    } else if (data.type === 'embedded') {
      // 如果是内嵌页面类型，将linkSrc值存入meta.iframeSrc
      data.meta = { ...data.meta, iframeSrc: data.linkSrc };
    }

    // 删除临时使用的linkSrc字段，因为后端API不需要此字段
    delete data.linkSrc;

    try {
      // 根据是否有ID判断是更新还是创建
      await (formData.value?.id
        ? updateMenu(formData.value.id, data) // 有ID，调用更新接口
        : createMenu(data)); // 无ID，调用创建接口

      // 先发送关闭抽屉的事件给父组件

      // 200ms后发送成功事件刷新列表，给抽屉足够时间关闭
      setTimeout(() => {
        emit('success');
      console.log('表单提交成功');
      }, 200);
    } catch (error) {
      console.error('表单提交失败:', error);
    } finally {
      console.log('表单提交结果:', data);
      // 无论成功失败，都恢复抽屉状态
      loading.value = false;
      drawerApi.close();
      drawerApi.setState({
        closeOnClickModal: true, // 恢复允许点击模态背景关闭
        closeOnPressEscape: true, // 恢复允许按Esc关闭
        confirmLoading: false, // 取消确认按钮加载状态
        loading: false, // 取消抽屉加载状态
      });

    }
  }
}

const getDrawerTitle = computed(() =>
  // 计算抽屉标题：根据是否有ID判断显示"编辑菜单"还是"创建菜单"
  formData.value?.id
    ? $t('ui.actionTitle.edit', [$t('system.menu.name')]) // 如果有ID，显示"编辑菜单"
    : $t('ui.actionTitle.create', [$t('system.menu.name')]), // 如果没有ID，显示"创建菜单"
);
</script>
<template>
  <Drawer class="w-full max-w-[800px]" :title="getDrawerTitle">
    <Form class="mx-4" :layout="isHorizontal ? 'horizontal' : 'vertical'" />
  </Drawer>
</template>
